﻿/**

 @Name：swui.taskbar 任务栏模块
 @Author：Zxq
 @License：MIT
    
 */
layui.define(['jquery', 'swui'], function (exports) {
    "use strict";

    var $ = layui.jquery, hoverTimer, outTimer;

    //任务栏构造函数
    var TaskBar = function () {
        swui.baseObject.call(this, 'taskbar');
        this.taskbarHeight = 40;
        this.taskbarWidth = 48;
        this.previewHeight = 100;
        this.previewWidth = 184;
        this.tasks = {};
        this.configs = {
            hoverDuring: 500,
            outDuring: 200
        };
    };

    TaskBar.prototype = {
        //初始化html元素及事件
        render: function (callback) {
            var othis = this;
            othis.elem = othis.configs.elem[0] || $('.swui-taskbar-task');
            othis.elem1 = othis.configs.elem[1] || $('.swui-taskbar-icon ul');
    
            othis.setData({urlcode:'uitaskbar'}, function (data) {
                othis.data = data;
                othis.renderElems();
                //调用渲染完毕的回调函数
                if (othis.Utils.isFunction(callback))
                    callback.call(this, othis);
            });
        }
        //渲染HTML
        ,renderElems: function () {
            if (this.data.length === 0) return;
            var othis = this;
            $(othis.data).each(function (index, item) {
                item.fix = true;
                othis.addTaskItem(item, null, true);
            });
            othis.resetEvents();
        }
        //任务栏事件
        ,resetEvents: function(){
            var othis = this,
                context = this.configs.contextmenu || [],
                barmenu = this.configs.barmenu || [],
                elemenu = this.configs.elemenu || [],
                events = this.configs.events || {};
            othis.resetEvent('scroll', othis.elem, function (e){//任务项超过一行(任务栏在顶部或底部横排)或一列(任务栏靠左或靠右竖排)时滚动事件
                switch (othis.configs.taskbarMode) {
                    case 'left':
                    case 'right':
                        var s = $(this).scrollLeft();
                        if (s%othis.taskbarWidth === 0) {
                            othis.configs.taskPositionX = s;
                            return;
                        }
                        if (othis.configs.taskPositionX < s)//向右滚动
                            s = Math.ceil(s/othis.taskbarWidth)*othis.taskbarWidth;
                        else s = Math.floor(s/othis.taskbarWidth)*othis.taskbarWidth;//向左滚动
                        $(this).scrollLeft(s);
                        othis.configs.taskPositionX = s;
                        break;
                    case 'top':
                    case 'bottom':
                    default:
                        var h = $(this).scrollTop();
                        if (h%othis.taskbarHeight === 0) {
                            othis.configs.taskPositionY = h;
                            return;
                        }
                        if (othis.configs.taskPositionY < h)//向下滚动
                            h = Math.ceil(h/othis.taskbarHeight)*othis.taskbarHeight;
                        else h = Math.floor(h/othis.taskbarHeight)*othis.taskbarHeight;//向上滚动
                        $(this).scrollTop(h);
                        othis.configs.taskPositionY = h;
                        break;
                }
            });
            //任务项点击事件
            othis.resetEvent('mouseup', '> li', function (e) {
                var target = e.target||e.srcElement;
                var $ul = $(target).closest('ul');
                var current = this;
                if (e.button === 2) {
                    var pos = {};
                    if (!$ul.is('.swui-taskbar-task')) {
                        if (!$ul.parent().is('li.swui-taskitems-on')) {
                            if (elemenu.length > 0) {//预览图右键菜单(最大化、最小化、还原、关闭)
                                pos = {left:e.clientX+'px',top:e.clientY+'px'};
                                othis.ContextMenu(target, elemenu, 'app-contextmenu', pos, $(current).data('code'), $(target).closest('li'), function(){ $ul.hide();$(current).removeClass('swui-taskitems-on'); });
                                $(current).addClass('swui-taskitems-on');
                            }
                            else $ul.hide();
                        }
                    }
                    else if (context.length > 0) {//重置右键菜单
                        //隐藏预览菜单
                        clearTimeout(hoverTimer);
                        $(current).removeClass('swui-taskitems-on').children('ul').hide();
                        switch (othis.configs.taskbarMode) {
                            case 'left':
                            case 'right':
                                pos.top = $(current).offset().top + 'px';
                                pos[othis.configs.taskbarMode] = othis.taskbarWidth + 'px';
                                break;
                            case 'top':
                            case 'bottom':
                            default:
                                pos.left = ($(current).offset().left - 76) + 'px';
                                pos[othis.configs.taskbarMode === 'top' ? 'top' : 'bottom'] = othis.taskbarHeight + 'px';
                                break;
                        }
                        othis.ContextMenu(target, context, 'task-contextmenu', pos, $(current).data('code'), $(current), { resetTask: function(){  } });
                        $(current).addClass('swui-task-menu').siblings().removeClass('swui-task-menu');
                    }
                }
                else if (e.button == 0 && othis.Utils.isFunction(events.click)) {//重置左键点击事件
                    othis.sp(event);//阻止事件冒泡
                    var code = $(this).data('code');
                    events.click.call(this, othis.tasks[code],event);
                }
            }, othis.elem);
            //任务小图标单击事件  ->  最好还是双击
            othis.resetEvent('click', '> li', function (e) {
                if (othis.Utils.isFunction(events.click)) {//重置左键点击事件
                    othis.sp(event);//阻止事件冒泡
                    var code = $(this).data('code');
                    events.click.call(this, othis.tasks[code],event);
                }
            }, othis.elem1);
            //任务栏空白处右键菜单
            othis.resetEvent('contextmenu', othis.elem, function (e) {
                var target = e.target || e.srcElement;
                if ($(target).closest('li').parent().is('.swui-taskbar-task') || $(target).closest('ul').parent().is('li')) return;
                var pos = {over:true,left:e.clientX+'px',top:e.clientY+'px'};
                othis.ContextMenu(target, barmenu, 'task-contextmenu', pos);
            });
            //任务栏自动显示隐藏
            othis.resetEvent('mouseenter', '.swui-taskbar', function (e) {
                swui.setTaskBarHide('show');
            },swui.elems.body);
            othis.resetEvent('mouseleave', '.swui-taskbar', function (e) {
                swui.setTaskBarHide('hide');
            },swui.elems.body);
            //任务项鼠标移入事件
            othis.resetEvent('mouseenter', '> li', function (e) {
                var $li = $(this);
                hoverTimer = setTimeout(function (){
                    if ($li.hasClass('swui-task-on') && !$li.hasClass('swui-task-menu') && $li.siblings('.swui-taskitems-on').length === 0) {
                        $li.children('ul').show();
                    }
                }, othis.configs.hoverDuring);
            },othis.elem);
            //任务项鼠标移出事件
            othis.resetEvent('mouseleave', '> li', function (e) {
                clearTimeout(hoverTimer);
                var $li = $(this);
                setTimeout(function (){
                    if ($li.hasClass('swui-task-on') && !$li.hasClass('swui-task-menu') && !$li.hasClass('swui-taskitems-on')) {
                        $li.children('ul').hide();
                    }
                }, othis.configs.outDuring);
            },othis.elem);
            //任务项窗口关联html元素事件(mouseenter、mouseleave、mouseup等)
            for (var evt in events) {
                if (evt == 'click') continue;
                othis.resetEvent(evt, 'li.swui-task-on > ul > li', function (event) {
                    var type = event.type;
                    if (!othis.Utils.isFunction(events[type]))
                        return;
                    return events[type].call(this, this, event);
                    //othis.sp(event);//阻止事件冒泡
                },othis.elem);
            }
        }
        ,resizeEvent: function(e){
            this.resetTaskBar(false);
            $('.task-contextmenu').remove();//任务栏、任务项右键菜单移除
        }
        //任务栏改变停靠位置
        ,changeMode: function (mode) {
            if (this.configs.taskbarMode === mode) return;
            this.configs.taskbarMode = mode;
            this.resetTaskBar(true);
        }
        //重置任务栏
        ,resetTaskBar: function (modeChange) {
            var w,h;
            var othis = this;
            othis.elem.attr('class', othis.elem.attr('class').replace(/\brows.*?\b/g, '').replace(/(^\s*)|(\s*$)/g, ""));
            switch(othis.configs.taskbarMode){
                case 'left':
                case 'right':
                    h = Math.floor((othis.elem.height()+1) / (othis.taskbarHeight+1));
                    othis.elem.addClass('rows'+h);
                    w = Math.floor(othis.elem.prop('scrollWidth') / othis.taskbarWidth);
                    break;
                case 'top':
                case 'bottom':
                default:
                    h = Math.floor(othis.elem.prop('scrollHeight') / othis.taskbarHeight);
                    w = Math.floor((othis.elem.width()+1) / (othis.taskbarWidth+1)); 
                    break;
            }
            if (h === othis.configs.taskRows && w === othis.configs.taskColumns && !modeChange) //没改变任务栏模式
                return;
            //行数或列数有改变则重置预览层偏移位置
            othis.elem.find('> li > ul').each(function(index, item){
                othis.setPreview($(item));
            });
            othis.setIconPreview();
            othis.configs.taskColumns = w;
            othis.configs.taskRows = h;
        }
        //添加任务项，有id表示只能打开一个窗口
        ,addTaskItem: function (option, callback, isInit) {
            if (!option.code) return;
            var othis = this;
            var isnew, taskItem;
            if (option.taskType === "icon") {
                if (option.id)
                    taskItem = this.elem1.find('> li[data-code="'+option.code+'"]');
                if (!taskItem || taskItem.length === 0) {
                    this.tasks[option.code] = option;
                    var html = '<li data-code="'+option.code+'"'+((option.fix && option.id) ? ' removeable="false"':'')+'><div>'+othis.getIconHtml(option.icon)+'</div></li>';
                    taskItem = $(html).appendTo(this.elem1);
                    othis.setIconPreview();
                }
                else taskItem[0].click();
                //非固定在任务栏的初始化则打开任务项
                if (othis.Utils.isFunction(callback)) {
                    var id = option.id || othis.Utils.guid();
                    isnew = !taskItem.attr(othis.winAttr);
                    callback(id,taskItem,isnew);//在callback回调函数中打开关联到item的layx窗口
                }
            } 
            else {
                taskItem = this.elem.find('> li[data-code="'+option.code+'"]');
                if (taskItem.length === 0) {
                    this.tasks[option.code] = option;
                    var html = '<li data-code="'+option.code+'"'+(option.fix ? ' class="swui-task-fixed"':'')+'><div>'+othis.getIconHtml(option.icon)+'</div><ul></ul></li>';
                    taskItem = $(html).appendTo(this.elem);
                }
                if (!isInit) {//非固定在任务栏的初始化则打开任务项
                    var ul = taskItem.children('ul');
                    var id = option.id || othis.Utils.guid();
                    var item = ul.find('li['+othis.winAttr+'="'+id+'"]');
                    isnew = (item.length === 0);
                    if (isnew) {
                        option = $.extend({width:800,height:600}, option);
                        var icon = option.icon ? othis.getIconHtml(option.icon, 20) : taskItem.children('div').html();
                        switch(othis.configs.taskbarMode) {
                            case 'left':
                            case 'right':
                                var h = Math.floor(option.height * othis.previewWidth / option.width);
                                item = $('<li><div style="width:'+othis.previewWidth+'px">'+icon+'&nbsp;'+option.title+'</div><canvas width="'+othis.previewWidth+'" height="'+h+'"></canvas></li>').appendTo(ul);
                                break;
                            case 'top':
                            case 'bottom':
                            default:
                                var w = Math.floor(option.width * othis.previewHeight / option.height);
                                item = $('<li><div style="width:'+w+'px">'+icon+'&nbsp;'+option.title+'</div><canvas width="'+w+'" height="'+othis.previewHeight+'"></canvas></li>').appendTo(ul);
                                break;
                        }
                        taskItem.addClass('swui-task-on');
                        othis.setPreview(ul);
                    }
                    else item[0].click();//存在则直接打开窗口
                    if (othis.Utils.isFunction(callback)) {
                        callback(id,item,isnew);//在callback回调函数中打开关联到item的layx窗口
                    }
                }
            }
            return taskItem;
        }
        //移除任务项
        ,removeTaskItem: function (option) {
            option = option || {};
            if (!option.code && !option.parent && !option.elem && !option.id) return;
            if (option.code && !option.parent) {
                option.parent = this.elem.find('li[data-code="'+option.code+'"]');
                if (option.parent.length === 0)
                    option.parent = this.elem1;
            }
            var othis = this, $main = option.parent, $lis;
            //任务小图标区域的任务项移除
            if ($main.hasClass('swui-taskbar-icon')) {
                if (option.elem && option.elem.attr('removeable') === 'false')
                    option.elem.removeAttr(othis.winAttr);
                else {
                    othis.setIconPreview();
                }
            }
            else {//任务栏的任务项移除
                if ($main && !option.id) {//移除同类任务项(.swui-taskbar-task li[data-code])
                    $main.find('> ul > li').each(function(index, item){
                        $(item).children('div:last').click();
                    });
                }
                else if (!$main && option.id) {
                    $lis = this.elem.find('> li > ul > li['+othis.winAttr+'="'+option.id+'"]');
                    $main = $lis.parent().parent();
                    $lis.children('div:last').click();
                }
                else {
                    $lis = $main.find('> ul > li['+othis.winAttr+'="'+option.id+'"]');
                    $lis.children('div:last').click();
                }
                if ($main.find('> ul > li').length === 0) {//没有任务子项
                    if ($main.hasClass('swui-task-fixed'))//固定在任务栏的移除焦点
                        $main.removeClass('swui-task-on swui-taskitems-on swui-task-menu swui-this');
                    else {//非固定任务项则删除，并计算后续任务项预览层偏移位置
                        var nexts = $main.nextAll();
                        $main.remove();
                        nexts.each(function(index, item){//计算后续任务项预览层偏移位置
                            var $ul = $(item).find('> ul');
                            othis.setPreview($ul);
                        });
                    }
                }
                else //还有任务子项，重新计算当前任务项预览层偏移位置
                    othis.setPreview($main.children('ul'));
            }
        }
        //任务项/任务小图标预览层调整
        ,setPreview: function ($ul){
            if ($ul == null || $ul.length === 0) return;
            //计算预览层偏移位置
            switch (this.configs.taskbarMode) {
                case 'left':
                case 'right':
                    var maxHeight = swui.elems.body.height();
                    $ul.css({width:'',height:'',left:''});
                    var h = $ul.height();
                    if (h>maxHeight) {
                        $ul.css({height:maxHeight});
                        $ul.css('top', 0);
                    }
                    else {
                        var offsettop = $ul.parent().offset().top;
                        var top = offsettop + (40-h)/2;
                        if (top + h > maxHeight) top = maxHeight - h;
                        $ul.css('top', top + 'px');
                    }
                    break;
                case 'top':
                case 'bottom':
                default:
                    var maxWidth = swui.elems.body.width();
                    $ul.css({width:'',height:'',top:''});
                    if ($ul.width()>maxWidth) $ul.css({width:maxWidth});
                    var offsetleft = $ul.parent().offset().left;
                    var left = offsetleft + (48-$ul.width())/2;
                    if (left < 0) left = 0;
                    $ul.css('left', left + 'px');
                    break;
            }
            //调整预览层高宽比
        }
        ,setIconPreview: function (){
            var $ul = this.elem1;
            if ($ul == null || $ul.length === 0) return;
            var count = $ul.children().length;
            //计算预览层偏移位置
            switch (this.configs.taskbarMode) {
                case 'left':
                case 'right':
                    var rowCount = Math.ceil(count/3.0);
                    if (count > 3) count = 3;
                    $ul.css({width:count*40,top:(24 - (rowCount*40+2)) / 2,left:''});
                    break;
                case 'top':
                case 'bottom':
                default:
                    if (count > 3) count = 3;
                    $ul.css({width:count*40,left:(24 - (count*40+2)) / 2,top:''});
                    break;
            }
        }
    }

    var taskbar = new TaskBar();

    swui.taskbar = taskbar;

    exports(taskbar.MOD_NAME, {});

    delete layui.taskbar;
});